home *** CD-ROM | disk | FTP | other *** search
-
- /-----------------------------\
- | Xine - issue #1 - Phile 009 |
- \-----------------------------/
-
-
- Mutation Engines
- by JHB
-
-
- Since I first heard about the idea of a Mutation engine I was
- interested to see the code that would explain how such a devious piece of
- code could work. I had taken apart several viruses, but most mutation
- engines due to thier nature are difficult to dissassemble. So after
- seeing other people's code I decide to try my hand at this type of coding.
- This article will illustrate the path I took in designing and building a
- Mutation Engine.
- To start I will try to define what a Mutation engine is, its code that
- can be link or added to a regular program or virus that will:
-
- 1 Encrypt itself as well as the program that is linked to it
- 2 Create a Decryptor that will be run first before the main program
- 3 Each Decryptor that it creates has a different signature
-
- Ok, now lets explain the defination, a signature (when refering to code)
- is a piece of code that should be unique to that code. An example of this
- is the signature:
- EA 05 00 C0 07
- Which is the hex code for
- jmp 07c0:0005
- This (which some may reconize) is the first line of code for the Stoned
- virus though it is short piece of code, placing this piece of code in the
- first part of the boot sector use to cause many Av products to false
- alarm. (not tested lately)
- Now a true mutation engine could alter this code to some other code
- that would accomplish the same thing, though this is possible it would
- make the engine huge. Mutation Engine writers have taken a easier way out
- they encrypt the main code and the engine then put a decryptor as the
- first thing that is run.
- This means that the only signature that has to alter is the decryptor,
- this is the main type of engine that is created these days.
-
- The first part of the creation process is to create a
- encryptor/decryptor that this should be fairly simply encrytion. I played
- with the standard xor/add/sub but they were spotted immeditaly by TBAV and
- F-prot as encrypted code. Since the main idea of a mutation engine is to
- fool both people and scanners this was not a good start. Well while
- reading the usenet group I saw a mention of a encryption that uses
- shl/shr. Many people may wonder if you use a shl/shr the leading bit or
- end bit is lost this is not true it is moved the carry flag. By simply
- adding this to the front or end of the register (or word) you can have
- reversible encrytion. Now TBAV will find most of these except for even
- number shifts like 2,4,8 while F-prot seems to miss most of these( only
- in heurstices and the /parnoid). (I was told this is because the shl 2,4,8
- code can also be used as a quick multiply or divide, so tbav will not flag
- this encryption). So I soon had this as a decryption module
- mov bx,offset virus_code
- decrypt:
- mov cx,4 ;encrytion key
- mov ax,cs:[bx] ;get the word to encrypt
- again:
- clc ;not needed I was young forgive me ;)
- shl 1 ;ok so ax before this code is
- ; ax 1000 0000 0000 0000 cf = 0
- ;after the shl
- ; ax 0000 0000 0000 0000 cf = 1
- jnc no_high_bit ;
- inc ax ;this simpy makes ax =
- ; ax 0000 0000 0000 0001
- no_high_bit:
- dec cx
- jcxz done_unencr ;ok done shifting it again
- jmp short again ;shift it again
- done_enencr:
- mov cs:[bx],ax ;Store the decrypted code
- add bx,2 ; move our pointer
- dec dx ;track how much is left
- jnz decrypt
-
- virus_code:
-
- Ok, so there we have a decryptor now use a shr and you have the
- encryption routine (its in the code read it ;) ).
- Ok now at this point I have a encryption engine that will fool TBAV
- and F-prot ( unless you use the f-prot /paranoid which the average user
- just does not do) but this is not a mutation engine. Well one simple
- mutation is to change the registers its a simple thing just requires some
- research that debug or a decent assembly book will show. All assemble
- instructions are built in a pattern take
- push ax which in hex is
- 50h or 1001 0000b
- now
- push bx is
- 53h or 10010 011b
-
- note that the 3 last bits are they only thing that changes this follows
- through so that for the word registers
- ax = 000 0
- cx = 001 1
- dx = 010 2
- bx = 011 3
- sp = 100 4
- bp = 101 5
- si = 110 6
- di = 111 7
- Ok so with some simple and/or instruction we can change the registers
- any other register of course we must not just randomly change registers
- we have to track which register we have use and make sure that we change
- all bx to cx.
- This is where some people start to get lost because we start treating
- code we are going to run as data. Take this example:
-
- mov cx,0004 ;b90400h
- becomes
-
- shift_reg:
- db 0b9h ;10111 001 <- cx
- dw 0004
-
- Now the mutation for this code might look like this
-
- mov ax,[shift_reg] ;
- and ax,11111000h ;this will isolate the mov
- ;instruction
- or ax,00000111 ;this would make the instruction
- ;mov di
- A better way would be to use a random number generator and get a number
- between 0-7 then OR that into it rather than the constant I used. Of
- course you must track what registers you use as you go.
-
- Now using this technique we have a limited mutation engine and just so
- you do not forget F-prot still catches it. So the next simple mutation use
- a sorta undocumented form of the shl instruction.
-
- shl AX,1 D1 E0 1101 000 1 1110 0000 <-USUAL CODE
- SHL AX,1 D1 F0 1101 111 1 1110 0000 <-UNDOC
-
- SHL AX,1 C1 E0 01 <-USUAL CODE
- SHL AX,1 C1 F0 01 <-UNDOC
-
-
- D1 F0 <-APPEARS THAT NEITHER FP OR TB FIND IT
-
- Now the unuasual part while all of the above code does the same thing
- shift the bits in the AX reg left the ones with the F0h are not used by
- many assemblers. (Though I have read that a shareware Assembler may use
- these codes maybe to track code that was produced by it). Using the
- "undocumented" form will fool f-prot every time but the c1 f0 01 will flag
- tbav with (and I love this flag) " 1 found instruction that will require
- an 80186 processor or above" Like they have add no instructions to the
- code set after the 8086!! But for a virus generated code this would not be
- a flag you want. Since any flag that was not there before will cause a
- problem.
-
- Ok so we have a simple mutation a reversible simple encryption and at
- least 4 forms of the decryptor code not including the mutation of the
- registers. The next part is to add do nothing or noise code. This is
- where careful creativity comes into play. Noise instructions or Do
- nothing bytes are instructions that actauly do, do something they just do
- not affect your code. NOP, XCHG AX,AX are some examples of do nothing
- code. In the early days of mutation engines and herustic scanners just
- adding nops and xchg code could make the virus unscannable. But as
- scanners improved they now will watch for such do nothing code, either
- ignoring it and seeing the real code or warning the user that there is
- code that serves no purpose but to hide a virus. Again I found that you
- could use some of these ideas say 1 or two nops in a row but too many and
- TBAV went to red alert. So I thought instead of using just one byte
- instructions why not have routines that called interrupts. just find
- ones that do not affect to many regs or put push regs code pop regs this
- way none of the real code is affected. An Example
-
- noise_6:
- push ax ;1 get the shift flags only affects the
- mov ax,0200h ;3 ax reg so push it then pop it.
- int 16h ;2
- pop ax ;1
- end_noise_6:
-
-
- Combine all these ideas togther and you can have an interesting piece
- of code that will produce several differnt variations on the decryptor.
- Well thats about all for me. If your realy interested in fooling with
- making a mutation engine get ahold of of as many source codes as you can
- and examine them then attempt one on your own. Even if you fail in
- making a viable mutation engine you will understand them far better. I
- did not bother to make my code a true engine its an example thats all.
-
-
-